﻿namespace TFSChangeLog.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using Microsoft.TeamFoundation.Framework.Client;
    using TFSChangeLog.DataAccess;
    using TFSChangeLog.DataModel;
    using TFSChangeLog.Operations.Command;

    /// <summary>Summary description for <see cref="MainWindowViewModel"/> class.</summary>
    public class MainWindowViewModel : ViewModelBase
    {
        #region Events

        /// <summary>Summary description for <c>SelectProjectWorkStarted</c> event.</summary>
        public event EventHandler SelectProjectWorkStarted;

        /// <summary>Summary description for <c>SelectProjectWorkEnded</c> event.</summary>
        public event EventHandler SelectProjectWorkEnded;

        /// <summary>Summary description for <c>SelectProjectBranchNodeWorkStarted</c> event.</summary>
        public event EventHandler SelectProjectBranchNodeWorkStarted;

        /// <summary>Summary description for <c>SelectProjectBranchNodeWorkEnded</c> event.</summary>
        public event EventHandler SelectProjectBranchNodeWorkEnded;

        /// <summary>Summary description for <c>SelectGenerateReleaseNotesWorkstarted</c> event.</summary>
        public event EventHandler SelectGenerateReleaseNotesWorkstarted;

        /// <summary>Summary description for <c>SelectGenerateReleaseNotesWorkEnded</c> event.</summary>
        public event EventHandler SelectGenerateReleaseNotesWorkEnded;

        /// <summary>Summary description for <c>ChangeSetSelectionError</c> event.</summary>
        public event EventHandler ChangeSetSelectionError;

        /// <summary>Summary description for <c>EmptyFileExtensionErrorError</c> event.</summary>
        public event EventHandler EmptyFileExtensionError;

        /// <summary>
        /// Event handler for xml changes start
        /// </summary>
        public event EventHandler SelectGenerateXmlChnagesWorkStarted;

        /// <summary>
        /// Event handler for xml changes end
        /// </summary>
        public event EventHandler SelectGenerateXmlChnagesWorkEnded;

        #endregion

        #region Constructor

        /// <summary>Initializes a new instance of the <see cref="MainWindowViewModel"/> class.</summary>
        public MainWindowViewModel()
        {
            this.initialize();
            TFSChangeLogStaticConfigs.Initialize();
        }

        #endregion

        #region Data and Properties.

        /// <summary>Summary description for class level field of type <c>Microsoft.TeamFoundation.Framework.Client.TeamFoundationIdentity</c>.</summary>
        public TeamFoundationIdentity _currentUser;

        /// <summary>Summary description for class level field of type <c>string</c>.</summary>
        private string _tfsServerName;

        /// <summary>Gets or sets the value for TFSServerName.</summary>
        public string TFSServerName
        {
            get
            {
                return this._tfsServerName;
            }

            set
            {
                if (value == this._tfsServerName)
                    {
                        return;
                    }

                this._tfsServerName = value;

                this.OnPropertyChanged("TFSServerName");
            }
        }

        /// <summary>Summary description for class level field of type <c>string</c>.</summary>
        private string _TFSProjectName;

        /// <summary>Gets or sets the value for TFSProjectName.</summary>
        public string TFSProjectName
        {
            get
            {
                return this._TFSProjectName;
            }

            set
            {
                if (value == this._TFSProjectName)
                    {
                        return;
                    }

                this._TFSProjectName = value;

                this.OnPropertyChanged("TFSProjectName");
            }
        }

        /// <summary>Summary description for class level field of type <c>string</c>.</summary>
        private string _TFSProjectSelectedBranchName;

        /// <summary>Gets or sets the value for TFSProjectSelectedBranchName.</summary>
        public string TFSProjectSelectedBranchName
        {
            get
            {
                return this._TFSProjectSelectedBranchName;
            }

            set
            {
                if (value == this._TFSProjectSelectedBranchName)
                    {
                        return;
                    }

                this._TFSProjectSelectedBranchName = value;

                this.OnPropertyChanged("TFSProjectSelectedBranchName");
            }
        }

        /// <summary>Summary description for class level field of type <c>bool</c>.</summary>
        private bool _CanExecuteGenerateReleaseNotes = false;

        /// <summary>Gets or sets a value indicating whether CanExecuteGenerateReleaseNotes is true or false.</summary>
        public bool CanExecuteGenerateReleaseNotes
        {
            get
            {
                return this._CanExecuteGenerateReleaseNotes;
            }

            set
            {
                if (value == this._CanExecuteGenerateReleaseNotes)
                    {
                        return;
                    }

                this._CanExecuteGenerateReleaseNotes = value;

                this.OnPropertyChanged("CanExecuteGenerateReleaseNotes");
            }
        }

        /// <summary>
        /// Can exceute generate release notes.
        /// </summary>
        private bool _CanExecuteGenerateFileChanges = false;

        /// <summary>
        /// Generate xml changes.
        /// </summary>
        public bool CanExecuteGenerateFileChanges
        {
            get { return _CanExecuteGenerateFileChanges; }
            set
            {
                if (value == _CanExecuteGenerateFileChanges)
                    return;
                _CanExecuteGenerateFileChanges = value;
                base.OnPropertyChanged("CanExecuteGenerateFileChanges");
            }
        }

        /// <summary>Summary description for class level field of type <c>bool</c>.</summary>
        private bool _IsFromChangeSetsEnabled = false;

        /// <summary>Gets or sets a value indicating whether IsFromChangeSetsEnabled is true or false.</summary>
        public bool IsFromChangeSetsEnabled
        {
            get
            {
                return this._IsFromChangeSetsEnabled;
            }

            set
            {
                if (value == this._IsFromChangeSetsEnabled)
                    {
                        return;
                    }

                this._IsFromChangeSetsEnabled = value;

                this.OnPropertyChanged("IsFromChangeSetsEnabled");
            }
        }

        /// <summary>Summary description for class level field of type <c>bool</c>.</summary>
        private bool _IsToChangeSetsEnabled = false;

        /// <summary>Gets or sets a value indicating whether IsToChangeSetsEnabled is true or false.</summary>
        public bool IsToChangeSetsEnabled
        {
            get
            {
                return this._IsToChangeSetsEnabled;
            }

            set
            {
                if (value == this._IsToChangeSetsEnabled)
                    {
                        return;
                    }

                this._IsToChangeSetsEnabled = value;

                this.OnPropertyChanged("IsToChangeSetsEnabled");
            }
        }
        #region FromChangeSets

        /// <summary>Summary description for class level field of type <c>System.Collections.ObjectModel.ObservableCollection{TFSChangeLog.ViewModel.FromChangeSetViewModel}</c>.</summary>
        private ObservableCollection<FromChangeSetViewModel> _fromChangeSets;

        /// <summary>Gets (TODO: Fix the documentation here) :: Returns a read-only collection containing ChangeSets 
        /// for the From ComboBox.</summary>
        public ObservableCollection<FromChangeSetViewModel> FromChangeSets
        {
            get { return this._fromChangeSets; }

            set
            {
                if (value == this._fromChangeSets)
                {
                    return;
                }

                this._fromChangeSets = value;

                this.OnPropertyChanged("FromChangeSets");
            }
        }

        /// <summary>Summary description for class level field of type <c>TFSChangeLog.ViewModel.FromChangeSetViewModel</c>.</summary>
        private FromChangeSetViewModel _SelectedFromChangeSet;

        /// <summary>Gets or sets the value for SelectedFromChangeSet.</summary>
        public FromChangeSetViewModel SelectedFromChangeSet
        {
            get
            {
                return this._SelectedFromChangeSet;
            }

            set
            {
                if (value == this._SelectedFromChangeSet)
                    {
                        return;
                    }

                this._SelectedFromChangeSet = value;

                this.OnPropertyChanged("SelectedFromChangeSet");
            }
        }

        #endregion // FromChangeSets

        /// <summary>Summary description for class level field of type <c>System.Collections.ObjectModel.ObservableCollection{TFSChangeLog.ViewModel.ToChangeSetViewModel}</c>.</summary>
        private ObservableCollection<ToChangeSetViewModel> _toChangeSets;

        #region ToChangeSets

        /// <summary>Gets (TODO: Fix the documentation here) :: Returns a read-only collection containing ChangeSets 
        /// for the To ComboBox.</summary>
        public ObservableCollection<ToChangeSetViewModel> ToChangeSets
        {
            get { return this._toChangeSets; }

            set
            {
                if (value == this._toChangeSets)
                {
                    return;
                }

                this._toChangeSets = value;

                this.OnPropertyChanged("ToChangeSets");
            }
        }

        /// <summary>Summary description for class level field of type <c>TFSChangeLog.ViewModel.ToChangeSetViewModel</c>.</summary>
        private ToChangeSetViewModel _SelectedToChangeSet;

        /// <summary>Gets or sets the value for SelectedToChangeSet.</summary>
        public ToChangeSetViewModel SelectedToChangeSet
        {
            get
            {
                return this._SelectedToChangeSet;
            }

            set
            {
                if (value == this._SelectedToChangeSet)
                    {
                        return;
                    }

                this._SelectedToChangeSet = value;

                this.OnPropertyChanged("SelectedToChangeSet");
            }
        }

        #endregion // ToChangeSets

        /// <summary>Summary description for class level field of type <c>bool</c>.</summary>
        private bool _IsTxtFileEnabled = false;

        /// <summary>Gets or sets a value indicating whether IsTxtFileEnabled is true or false.</summary>
        public bool IsTxtFileEnabled
        {
            get
            {
                return this._IsTxtFileEnabled;
            }

            set
            {
                if (value == this._IsTxtFileEnabled)
                {
                    return;
                }

                this._IsTxtFileEnabled = value;

                this.OnPropertyChanged("IsTxtFileEnabled");
            }
        }

        /// <summary>
        /// file extension
        /// </summary>
        private string _fileExtension;

        /// <summary>
        /// file extension comma seprated string
        /// </summary>
        public string FileExtension
        {
            get { return _fileExtension; }
            set
            {
                if (value == _fileExtension)
                    return;

                _fileExtension = value;
                base.OnPropertyChanged("FileExtension");
            }
        }

        /// <summary>Summary description for class level field of type <c>TFSChangeLog.ViewModel.BranchViewModel</c>.</summary>
        private BranchViewModel _rootBranch;
        #endregion

        #region Child View Models

        /// <summary>Gets or sets (TODO: Fix the documentation here) :: Progress dialog view model.</summary>
        public ProgressDialogViewModel progressDialogViewModel { get; set; }

        #endregion

        #region Event Invokers

        /// <summary>
        /// Raises the WorkStarting event.
        /// </summary>
        internal void RaiseProjectSelectionWorkStartedEvent()
        {
            // Exit if no subscribers
            if (this.SelectProjectWorkStarted == null)
            {
                return;
            }

            // Raise event
            this.SelectProjectWorkStarted(this, new EventArgs());
        }

        /// <summary>
        /// Raises the WorkEnding event.
        /// </summary>
        internal void RaiseProjectSelectionWorkEndedEvent()
        {
            // Exit if no subscribers
            if (this.SelectProjectWorkEnded == null)
            {
                return;
            }

            // Raise event
            this.SelectProjectWorkEnded(this, new EventArgs());
        }

        /// <summary>
        /// Raises ProjectBranchNode GetChangeSet WorkStarting event.
        /// </summary>
        internal void RaiseProjectBranchNodeWorkStartedEvent()
        {
            // Exit if no subscribers
            if (this.SelectProjectBranchNodeWorkStarted == null)
            {
                return;
            }

            // Raise event
            this.SelectProjectBranchNodeWorkStarted(this, new EventArgs());
        }

        /// <summary>
        /// Raises ProjectBranchNode GetChangeSet WorkEnding event.
        /// </summary>
        internal void RaiseProjectBranchNodeWorkEndedEvent()
        {
            // Exit if no subscribers
            if (this.SelectProjectBranchNodeWorkEnded == null)
            {
                return;
            }

            // Raise event
            this.SelectProjectBranchNodeWorkEnded(this, new EventArgs());
        }

        /// <summary>
        /// Raises ProjectBranchNode GetChangeSet WorkStarting event.
        /// </summary>
        internal void RaiseGenerateReleaseNotesWorkStartedEvent()
        {
            // Exit if no subscribers
            if (this.SelectGenerateReleaseNotesWorkstarted == null)
            {
                return;
            }

            // Raise event
            this.SelectGenerateReleaseNotesWorkstarted(this, new EventArgs());
        }

        /// <summary>
        /// Raises ProjectBranchNode GetChangeSet WorkEnding event.
        /// </summary>
        internal void RaiseGenerateReleaseNotesWorkEndedEvent()
        {
            // Exit if no subscribers
            if (this.SelectGenerateReleaseNotesWorkEnded == null)
            {
                return;
            }

            // Raise event
            this.SelectGenerateReleaseNotesWorkEnded(this, new EventArgs());
        }

        /// <summary>
        /// Raises the WorkStarting event.
        /// </summary>
        internal void RaiseEmptyFileExtensionError()
        {
            // Exit if no subscribers
            if (this.EmptyFileExtensionError == null)
            {
                return;
            }

            // Raise event
            this.EmptyFileExtensionError(this, new EventArgs());
        }

        /// <summary>
        /// Raises the WorkStarting event.
        /// </summary>
        internal void RaiseChangeSetSelectionError()
        {
            // Exit if no subscribers
            if (this.ChangeSetSelectionError == null)
            {
                return;
            }

            // Raise event
            this.ChangeSetSelectionError(this, new EventArgs());
        }

        /// <summary>
        /// Raise Xml changes work started event
        /// </summary>
        internal void RaiseGenerateXmlChangesWorkStartedEvent()
        {
            // Exit if no subscribers
            if (SelectGenerateXmlChnagesWorkStarted == null) return;

            // Raise event
            SelectGenerateXmlChnagesWorkStarted(this, new EventArgs());
        }

        /// <summary>
        /// Raises Xml changes work ended event
        /// </summary>
        internal void RaiseGenerateXmlChangesWorkEndedEvent()
        {
            // Exit if no subscribers
            if (SelectGenerateXmlChnagesWorkEnded == null) return;

            // Raise event
            SelectGenerateXmlChnagesWorkEnded(this, new EventArgs());
        }

        #endregion

        #region FirstGeneration

        /// <summary>Summary description for class level field of type <c>System.Collections.ObjectModel.ObservableCollection{TFSChangeLog.ViewModel.BranchViewModel}</c>.</summary>
        private ObservableCollection<BranchViewModel> _firstGeneration;

        /// <summary>Gets (TODO: Fix the documentation here) :: Returns a read-only collection containing the first object 
        /// in the family tree, to which the TreeView can bind.</summary>
        public ObservableCollection<BranchViewModel> FirstGeneration
        {
            get { return this._firstGeneration; }
        }

        #endregion // FirstGeneration

        #region methods

        /// <summary>Summary description for <c>MainWindowViewModel</c> method.</summary>
        public void ResetAllUIItems()
        {
            this.CanExecuteGenerateReleaseNotes = false;
            this.CanExecuteGenerateFileChanges = false;
            
            if (this.FromChangeSets != null)
            {
                this.FromChangeSets.Clear();
                this.IsFromChangeSetsEnabled = false;
            }

            if (this.ToChangeSets != null)
            {
                this.ToChangeSets.Clear();
                this.IsToChangeSetsEnabled = false;
            }

            if (this.FirstGeneration != null)
            {
                this.FirstGeneration.Clear();
            }

            if (!string.IsNullOrEmpty(FileExtension))
            {
                this.FileExtension = string.Empty; 
            }

            this.IsTxtFileEnabled = false;
        }

        /// <summary>Summary description for <c>MainWindowViewModel</c> method.</summary>
        /// <param name="rootBranch">TODO: Summary description for <c>rootBranch</c> parameter of type <c>TFSChangeLog.DataModel.Branch</c>.</param>
        public void UpdateBranchTreeStructure(Branch rootBranch)
        {
            this._rootBranch = new BranchViewModel(rootBranch);

            this._firstGeneration = new ObservableCollection<BranchViewModel>(
                new BranchViewModel[] 
                { 
                    this._rootBranch 
                });
            this.OnPropertyChanged("FirstGeneration");
        }

        /// <summary>Summary description for <c>MainWindowViewModel</c> method.</summary>
        private void initialize()
        {
            // Inidialize Commands.
            this.GenerateCommands();

            // Initialize child ViewModel(s)
            this.progressDialogViewModel = new ProgressDialogViewModel(this);
        }

        /// <summary>Summary description for <c>MainWindowViewModel</c> method.</summary>
        private void GenerateCommands()
        {
            this.ShowProjectSelector = new ShowProjectSelectorCommand(this).ShowProjectSelector;
            this.ShowSelectedProjectBranchNode = new ShowSelectedProjectBranchNodeCommand(this).ShowSelectedProjectBranchNode;
            this.GenerateReleaseNotes = new GenerateReleaseNotesCommand(this).GenerateReleaseNotes;
            this.GenerateXmlChanges = new GenerateXmlChangesCommand(this).GenerateXMLChanges;
        }

        #endregion

        #region MVVM Commands

        /// <summary>Gets the value for ShowProjectSelector.</summary>
        public ICommand ShowProjectSelector { get; private set; }

        /// <summary>Gets the value for ShowSelectedProjectBranchNode.</summary>
        public ICommand ShowSelectedProjectBranchNode { get; private set; }

        /// <summary>Gets the value for GenerateReleaseNotes.</summary>
        public ICommand GenerateReleaseNotes { get; private set; }

        /// <summary>
        /// Generate xml changes command.
        /// </summary>
        public ICommand GenerateXmlChanges { get; private set; }

        #endregion
    }
}
